package com.cskaoyan.wordmemorize.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cskaoyan.wordmemorize.converter.ReviewConverter;
import com.cskaoyan.wordmemorize.dao.entity.UserCheckinStatisticsDO;
import com.cskaoyan.wordmemorize.dao.entity.UserRevStatisticsDO;
import com.cskaoyan.wordmemorize.dao.entity.UserVocRevDO;
import com.cskaoyan.wordmemorize.dao.mapper.UserCheckinStatisticsMapper;
import com.cskaoyan.wordmemorize.dao.mapper.UserRevStatisticsMapper;
import com.cskaoyan.wordmemorize.dao.mapper.UserVocRevMapper;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.dto.app.DownLoadUserReviewDTO;
import com.cskaoyan.wordmemorize.dto.app.UserReviewStatisticsDTO;
import com.cskaoyan.wordmemorize.dto.app.UserVocRevDTO;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.UserReviewDataCommand;
import com.cskaoyan.wordmemorize.request.UserReviewStatisticsCommand;
import com.cskaoyan.wordmemorize.service.UserReviewService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.List;

@Service
public class UserReviewServiceImpl implements UserReviewService {
    @Autowired
    UserVocRevMapper userVocRevMapper;
    @Autowired
    UserRevStatisticsMapper userRevStatisticsMapper;
    @Autowired
    ReviewConverter reviewConverter;
    @Autowired
    UserCheckinStatisticsMapper userCheckinStatisticsMapper;

    @Transactional
    @Override
    public void synchronizeUserReviewData(UserReviewDataCommand command, Long userId) {
        UserRevStatisticsDO newUserRevStatisticsDO = reviewConverter.userRevStatisticsCommand2DO(command.getRevStatisticsCommand());
        newUserRevStatisticsDO.setUserId(userId);
        // todo:获取当天的用户学习时间,用来更新用户总的复习时间user_checkin_statistics中的total_time字段
        Long newStudyTime = newUserRevStatisticsDO.getStudyTime();

        // todo:判断数据库表user_rev_statistic中是否有当天的复习统计数据，若无，直接插入，若有，进行更新
        LambdaQueryWrapper<UserRevStatisticsDO> userRevStatisticsQueryWrapper = new LambdaQueryWrapper<>();
        userRevStatisticsQueryWrapper.eq(UserRevStatisticsDO::getUserId, userId)
                .eq(UserRevStatisticsDO::getReviewDate, LocalDate.now());
        UserRevStatisticsDO oldUserRevStatisticsDO = userRevStatisticsMapper.selectOne(userRevStatisticsQueryWrapper);
        if (oldUserRevStatisticsDO == null) {
            // todo:数据库中无当天复习统计数据，直接插入
            userRevStatisticsMapper.insert(newUserRevStatisticsDO);
            // todo:更新user_checkin_statistics中的total_time字段，直接增加
            LambdaQueryWrapper<UserCheckinStatisticsDO> userCheckinStatisticsQueryWrapper = new LambdaQueryWrapper<>();
            userCheckinStatisticsQueryWrapper.eq(UserCheckinStatisticsDO::getUserId, userId);
            UserCheckinStatisticsDO userCheckinStatisticsDO = userCheckinStatisticsMapper.selectOne(userCheckinStatisticsQueryWrapper);
            userCheckinStatisticsDO.setTotalTime(userCheckinStatisticsDO.getTotalTime() + newStudyTime);

            LambdaUpdateWrapper<UserCheckinStatisticsDO> userCheckinStatisticsUpdateWrapper = new LambdaUpdateWrapper<>();
            userCheckinStatisticsUpdateWrapper.eq(UserCheckinStatisticsDO::getUserId, userId);
            userCheckinStatisticsMapper.update(userCheckinStatisticsDO, userCheckinStatisticsUpdateWrapper);
            return;
        }
        // todo:数据库中有当天复习统计数据，更新
        userRevStatisticsMapper.update(newUserRevStatisticsDO, userRevStatisticsQueryWrapper);

        // todo:更新user_checkin_statistics中的total_time字段，减去之前的学习时间再增加
        Long oldStudyTime = oldUserRevStatisticsDO.getStudyTime();
        LambdaQueryWrapper<UserCheckinStatisticsDO> userCheckinStatisticsQueryWrapper = new LambdaQueryWrapper<>();
        userCheckinStatisticsQueryWrapper.eq(UserCheckinStatisticsDO::getUserId, userId);
        UserCheckinStatisticsDO userCheckinStatisticsDO = userCheckinStatisticsMapper.selectOne(userCheckinStatisticsQueryWrapper);
        userCheckinStatisticsDO.setTotalTime(userCheckinStatisticsDO.getTotalTime() + newStudyTime - oldStudyTime);

        LambdaUpdateWrapper<UserCheckinStatisticsDO> userCheckinStatisticsUpdateWrapper = new LambdaUpdateWrapper<>();
        userCheckinStatisticsUpdateWrapper.eq(UserCheckinStatisticsDO::getUserId, userId);
        userCheckinStatisticsMapper.update(userCheckinStatisticsDO, userCheckinStatisticsUpdateWrapper);

        // todo:对单词复习数据user_voc_rev,直接更新
        List<UserVocRevDO> userVocRevDOS = reviewConverter.userVocRevCommands2DOs(command.getVocRevCommands());
        userVocRevDOS.forEach(userVocRevDO -> userVocRevDO.setUserId(userId));
        LambdaUpdateWrapper<UserVocRevDO> userVocRevUpdateWrapper = new LambdaUpdateWrapper<>();
        userVocRevDOS.forEach(userVocRevDO -> {
            userVocRevDO.setId(null);
            userVocRevUpdateWrapper.clear();
            userVocRevUpdateWrapper.eq(UserVocRevDO::getUserId, userId)
                    .eq(UserVocRevDO::getVocId, userVocRevDO.getVocId());
            userVocRevMapper.update(userVocRevDO, userVocRevUpdateWrapper);
        });


    }

    @Override
    public DownLoadUserReviewDTO downloadUserReviewData(PageRequest pageRequest, Long userId) {
        LambdaQueryWrapper<UserVocRevDO> userVocRevQueryWrapper = new LambdaQueryWrapper<>();
        userVocRevQueryWrapper.eq(UserVocRevDO::getUserId, userId);
        LambdaQueryWrapper<UserRevStatisticsDO> userRevStatisticsQueryWrapper = new LambdaQueryWrapper<>();
        userRevStatisticsQueryWrapper.eq(UserRevStatisticsDO::getUserId, userId);

        if (null == pageRequest || 0 == pageRequest.getPageNum()) {
            // todo:全表查询
            List<UserVocRevDO> userVocRevDOS = userVocRevMapper.selectList(userVocRevQueryWrapper);
            List<UserRevStatisticsDO> userRevStatisticsDOS = userRevStatisticsMapper.selectList(userRevStatisticsQueryWrapper);
            PageDTO<UserVocRevDTO> userVocRevDTOPageDTO = reviewConverter.userVocRevPage2PageDTO(userVocRevDOS, (long) userVocRevDOS.size());
            PageDTO<UserReviewStatisticsDTO> userReviewStatisticsDTOPageDTO =
                    reviewConverter.userRevStatistcsPage2PageDTO(userRevStatisticsDOS, (long) userRevStatisticsDOS.size());
            DownLoadUserReviewDTO downLoadUserReviewDTO = DownLoadUserReviewDTO.builder()
                    .userVocRevPage(userVocRevDTOPageDTO)
                    .userReviewStatisticsPage(userReviewStatisticsDTOPageDTO)
                    .build();
            return downLoadUserReviewDTO;
        }
        // todo:分页查询
        Page<UserVocRevDO> userVocRevDOPageParam = new Page<>(pageRequest.getPageNum(), pageRequest.getCount());
        Page<UserRevStatisticsDO> userRevStatisticsDOPageParam = new Page<>(pageRequest.getPageNum(), pageRequest.getCount());
        Page<UserVocRevDO> userVocRevDOPage = userVocRevMapper.selectPage(userVocRevDOPageParam, userVocRevQueryWrapper);
        Page<UserRevStatisticsDO> userRevStatisticsDOPage = userRevStatisticsMapper.selectPage(userRevStatisticsDOPageParam, userRevStatisticsQueryWrapper);
        PageDTO<UserVocRevDTO> userVocRevDTOPageDTO = reviewConverter.userVocRevPage2PageDTO(userVocRevDOPage.getRecords(), userVocRevDOPage.getTotal());
        PageDTO<UserReviewStatisticsDTO> userReviewStatisticsDTOPageDTO =
                reviewConverter.userRevStatistcsPage2PageDTO(userRevStatisticsDOPage.getRecords(), userRevStatisticsDOPage.getTotal());
        DownLoadUserReviewDTO downLoadUserReviewDTO = DownLoadUserReviewDTO.builder()
                .userVocRevPage(userVocRevDTOPageDTO)
                .userReviewStatisticsPage(userReviewStatisticsDTOPageDTO)
                .build();
        return downLoadUserReviewDTO;
    }

    @Override
    public void addUserRovRev(List<Long> vocIds, Long userId) {
        UserVocRevDO userVocRevDO = UserVocRevDO.builder()
                .userId(userId)
                .factor(1.4)
                .reviewInterval(1)
                .nextReviewDate(LocalDate.now())
                .type(0)
                .consecutiveFailCount(0)
                .totalReview(0)
                .build();
        vocIds.forEach(vocId -> {
            userVocRevDO.setId(null);// todo:将插入数据时自动生成的主键改为null,防止主键重复
            userVocRevDO.setVocId(vocId);
            userVocRevMapper.insert(userVocRevDO);
        });
    }
}
